<!DOCTYPE html>
<html lang="en">

<!-- Head tag -->
<head><meta name="generator" content="Hexo 3.9.0">

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!--Description-->
    

    <!--Author-->
    
        <meta name="author" content="ck">
    

    <!--Open Graph Title-->
    
        <meta property="og:title" content="CK&#39;s blogs">
    

    <!--Open Graph Description-->
    

    <!--Open Graph Site Name-->
    <meta property="og:site_name" content="CK&#39;s blogs">

    <!--Type page-->
    
        <meta property="og:type" content="website">
    

    <!--Page Cover-->
    

    <meta name="twitter:card" content="summary">
    

    <!-- Title -->
    
    <title>CK&#39;s blogs</title>

    <!-- Bootstrap Core CSS -->
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" integrity="sha384-y3tfxAZXuh4HwSYylfB+J125MxIs6mR5FOHamPBG064zB+AFeWH94NdvaCBm8qnd" crossorigin="anonymous">

    <!-- Custom Fonts -->
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- Gallery -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.css" type="text/css" rel="stylesheet">

    <!-- Custom CSS -->
    <link rel="stylesheet" href="/blog/css/style.css">

    <!-- Google Analytics -->
    


</head>


<body>

<div class="bg-gradient"></div>
<div class="bg-pattern"></div>

<!-- Menu -->
<!--Menu Links and Overlay-->
<div class="menu-bg">
    <div class="menu-container">
        <ul>
            
            <li class="menu-item">
                <a href="/blog/">
                    Home
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/archives">
                    Archives
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/2019/09/04/本人简历/">
                    About
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/tags">
                    Tags
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/categories">
                    Categories
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/contact.html">
                    Contact
                </a>
            </li>
            
        </ul>
    </div>
</div>

<!--Hamburger Icon-->
<nav>
    <a href="#menu"></a>
</nav>

<div class="container">

    <!-- Main Content -->
    <div class="row">
    <div class="col-sm-12">

        <!--Title and Logo-->
        <header>
    <div class="logo">
        <a href="/blog/"><i class="logo-icon fa fa-cube" aria-hidden="true"></i></a>
        
            <h1 id="main-title" class="title">CK's blogs</h1>
        
    </div>
</header>

        <section class="main">
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/10/25/tars框架环境基础搭建/">
                tars框架环境基础搭建
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-10-25</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="tars环境部署"><a href="#tars环境部署" class="headerlink" title="tars环境部署"></a>tars环境部署</h1><p>注意：这里依据Git上的tars搭建步骤整理而来，且必须依赖mysql  且未和任何业务有瓜葛  纯框架环境搭建</p>
<p>参考： </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">https://max.book118.com/html/2017/0527/109698528.shtm</span><br><span class="line">https://github.com/TarsCloud/Tars/blob/master/Install.zh.md</span><br></pre></td></tr></table></figure>

<p>环境： centos7.3-x86_64  kernel ：3.10    </p>
<p>上刺刀， 不是 上干货！</p>
<p>1,依赖</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">yum install mpfr -y</span><br><span class="line">yum install gmp -y</span><br><span class="line">yum install *mpc* -y</span><br><span class="line">yum install glibc-static libstdc++-static -y</span><br><span class="line">yum -y install gcc gcc-c++</span><br><span class="line">yum -y install autoconf automake libtool curl make g++ unzip zlib zlib-devel</span><br><span class="line">yum install glibc-devel -y</span><br><span class="line">yum install cmake -y</span><br><span class="line">yum install perl -y</span><br><span class="line">yum install -y git</span><br><span class="line">yum install ncurses-devel -y</span><br></pre></td></tr></table></figure>

<p>2，安装gcc</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"># 安装，下载好包并放在/mnt下面</span><br><span class="line">cd /mnt</span><br><span class="line">wget http://ftp.gnu.org/gnu/gcc/gcc-6.3.0/gcc-6.3.0.tar.gz</span><br><span class="line">tar  fx gcc-6.3.0.tar.gz</span><br><span class="line">cd gcc-6.3.0/</span><br><span class="line">./contrib/download_prerequisites</span><br><span class="line">./configure -enable-checking=release -enable-languages=c,c++ -disable-multilib</span><br><span class="line">make -j2</span><br><span class="line">make install</span><br><span class="line"># 配置gcc环境变量</span><br><span class="line">mv /usr/bin/gcc /usr/bin/gcc4.4.7</span><br><span class="line">ln -s /usr/local/bin/gcc /usr/bin/gcc</span><br><span class="line">mv /usr/bin/g++ /usr/bin/g++4.4.7</span><br><span class="line">ln -s /usr/local/bin/g++ /usr/bin/g++</span><br><span class="line">mv /usr/bin/cc /usr/bin/cc4.4.7</span><br><span class="line">ln -s /usr/local/bin/cc /usr/bin/cc</span><br><span class="line">mv /usr/bin/c++ /usr/bin/c++4.4.7</span><br><span class="line">ln -s /usr/local/bin/c++ /usr/bin/c++</span><br><span class="line">gcc --version</span><br><span class="line">echo &quot;/usr/local/lib64&quot; &gt;&gt;/etc/ld.so.conf</span><br><span class="line">ldconfig</span><br></pre></td></tr></table></figure>

<p>3，安装protoc-3.6.1</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt</span><br><span class="line">unzip protobuf-master.zip</span><br><span class="line">cd protobuf-master/</span><br><span class="line">./autogen.sh</span><br><span class="line">./configure</span><br><span class="line">make</span><br><span class="line">make check</span><br><span class="line">make install</span><br><span class="line">protoc --\version</span><br></pre></td></tr></table></figure>

<p>4，安装jdk</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt</span><br><span class="line">tar xf jdk-8u181-linux-x64.tar.gz -C /usr/java</span><br><span class="line">cat &gt;&gt; /etc/profile &lt;&lt; EOF</span><br><span class="line">export JAVA_HOME=/usr/java/jdk1.8.0_181</span><br><span class="line">export JRE_HOME=\$&#123;JAVA_HOME&#125;/jre</span><br><span class="line">export CLASSPATH=.:\$&#123;JAVA_HOME&#125;/lib:\$&#123;JRE_HOME&#125;/lib</span><br><span class="line">export PATH=\$&#123;JAVA_HOME&#125;/bin:\$PATH</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">source /etc/profile</span><br><span class="line">echo $JAVA_HOME</span><br></pre></td></tr></table></figure>

<p>5,安装mysql-5.6</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 安装mysql</span><br><span class="line">useradd mysql</span><br><span class="line">tar fx mysql-5.6.35.tar.gz</span><br><span class="line">cd  mysql-5.6.35/</span><br><span class="line">cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci</span><br><span class="line">make &amp;&amp; make install</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">#配置mysql</span><br><span class="line">yum -y install perl</span><br><span class="line">cd /usr/local/mysql/</span><br><span class="line">rm  -rf /usr/local/mysql/data/</span><br><span class="line">mkdir -p /data/mysql-data</span><br><span class="line">ln -s /data/mysql-data/ /usr/local/mysql/data</span><br><span class="line">chown -R mysql. /data/mysql-data/</span><br><span class="line">chown -R mysql. /usr/local/mysql/data/</span><br><span class="line">cp support-files/mysql.server /etc/init.d/mysql</span><br><span class="line">rm -rf /etc/my.cnf</span><br><span class="line">yum install -y perl-Module-Install.noarch</span><br><span class="line">perl scripts/mysql_install_db --user=mysql</span><br></pre></td></tr></table></figure>

<p>[root@bogon mysql]# vim /usr/local/mysql/my.cnf</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"># For advice on how to change settings please see</span><br><span class="line"># http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html</span><br><span class="line"></span><br><span class="line">[mysqld]</span><br><span class="line"></span><br><span class="line"># Remove leading # and set to the amount of RAM for the most important data</span><br><span class="line"># cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.</span><br><span class="line">innodb_buffer_pool_size = 128M</span><br><span class="line"></span><br><span class="line"># Remove leading # to turn on a very important data integrity option: logging</span><br><span class="line"># changes to the binary log between backups.</span><br><span class="line">log_bin</span><br><span class="line"></span><br><span class="line"># These are commonly set, remove the # and set as required.</span><br><span class="line">basedir = /usr/local/mysql</span><br><span class="line">datadir = /usr/local/mysql/data</span><br><span class="line"># port = .....</span><br><span class="line"># server_id = .....</span><br><span class="line">socket = /tmp/mysql.sock</span><br><span class="line">bind-address=172.25.196.66</span><br><span class="line"></span><br><span class="line"># Remove leading # to set options mainly useful for reporting servers.</span><br><span class="line"># The server defaults are faster for transactions and fast SELECTs.</span><br><span class="line"># Adjust sizes as needed, experiment to find the optimal values.</span><br><span class="line">join_buffer_size = 128M</span><br><span class="line">sort_buffer_size = 2M</span><br><span class="line">read_rnd_buffer_size = 2M  </span><br><span class="line"></span><br><span class="line">sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES</span><br><span class="line">~</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ln -s /usr/local/mysql /usr/local/mysql-5.6.35</span><br><span class="line">service mysql start</span><br><span class="line">netstat -plnt |grep 3306</span><br><span class="line">chkconfig mysql on</span><br><span class="line">mkdir -p /var/lib/mysql/</span><br><span class="line">ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 添加环境变量</span><br><span class="line">echo &quot;PATH=$PATH:/usr/local/mysql/bin&quot; &gt;&gt;/etc/profile</span><br><span class="line">echo &quot;export PATH&quot; &gt;&gt;/etc/profile</span><br><span class="line">source /etc/profile</span><br><span class="line">service mysql restart</span><br><span class="line">./bin/mysqladmin -u root password &apos;root@appinside&apos;</span><br><span class="line">./bin/mysqladmin -u root -h 172.25.196.66 password &apos;root@appinside&apos;</span><br><span class="line">echo &quot;/usr/local/mysql/lib/&quot; &gt;&gt;/etc/ld.so.conf</span><br><span class="line">ldconfig</span><br></pre></td></tr></table></figure>

<p>6，安装resin</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cd /usr/local/</span><br><span class="line">wget http://www.caucho.com/download/resin-4.0.49.tar.gz</span><br><span class="line">tar xf resin-4.0.49.tar.gz</span><br><span class="line">ln -s resin-4.0.49 resin</span><br></pre></td></tr></table></figure>

<p>7，安装maven</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt</span><br><span class="line">tar fx apache-maven-3.5.4-bin.tar.gz</span><br><span class="line">mv apache-maven-3.5.4 /usr/local/maven</span><br><span class="line">cp /etc/profile /etc/profile.bak</span><br><span class="line">echo &quot;export MVEN_HOME=/usr/local/maven&quot; &gt;&gt;/etc/profile</span><br><span class="line">echo &quot;export PATH=$MVEN_HOME/bin:$PATH&quot; &gt;&gt;/etc/profile</span><br><span class="line">source /etc/profile</span><br><span class="line">mvn -version</span><br></pre></td></tr></table></figure>

<p>8,安装web管理系统开发环境nvm</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash</span><br><span class="line">source ~/.bashrc</span><br><span class="line">nvm install v8.11.3</span><br><span class="line">npm install -g pm2 --registry=https://registry.npm.taobao.org</span><br></pre></td></tr></table></figure>

<p>9,安装bison组件和flex组件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum -y install bison flex</span><br></pre></td></tr></table></figure>

<p>10,安装Java语言工具包</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt</span><br><span class="line">tar fx thirdparty.tgz</span><br><span class="line">cd  thirdparty/tars-1.5.0/;ls</span><br><span class="line">-----&gt;</span><br><span class="line">build  docs           Install_faq.en.md  Install.md          Introduction.md  LICENSE.TXT  php      README.en.md  tup</span><br><span class="line">cpp    Install.en.md  Install_faq.md     Introduction.en.md  java             nodejs       plugins  README.md     web</span><br><span class="line"></span><br><span class="line">cd java</span><br><span class="line">mvn clean install</span><br><span class="line">mvn clean install -f core/client.pom.xml</span><br><span class="line">mvn clean install -f core/server.pom.xml</span><br></pre></td></tr></table></figure>

<p>12、安装c++环境</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">yum -y install dos2unix flex bison</span><br><span class="line"></span><br><span class="line">cd /mnt/thirdparty/tars-1.5.0/cpp/thirdparty</span><br><span class="line">git clone https://github.com/Tencent/rapidjson.git</span><br><span class="line"></span><br><span class="line">cd /mnt/thirdparty/tars-1.5.0/cpp/build/</span><br><span class="line">./build.sh all</span><br><span class="line">mkdir /usr/local/tars</span><br><span class="line">make install</span><br></pre></td></tr></table></figure>

<p>13、tars数据库环境初始化</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mysql -uroot -proot@appinside -e &quot;grant all on *.* to &apos;tars&apos;@&apos;%&apos; identified by &apos;tars2015&apos; with grant option;&quot;</span><br><span class="line">mysql -uroot -proot@appinside -e &quot;grant all on *.* to &apos;tars&apos;@&apos;localhost&apos; identified by &apos;tars2015&apos; with grant option;&quot;</span><br><span class="line">mysql -uroot -proot@appinside -e &quot;grant all on *.* to &apos;tars&apos;@&apos;$&#123;MachineName&#125;&apos; identified by &apos;tars2015&apos; with grant option;&quot;</span><br><span class="line">mysql -uroot -proot@appinside -e &quot;flush privileges;&quot;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt/thirtparty/tars-1.5.0/cpp/framework/sql</span><br><span class="line">sed -i &quot;s/192.168.2.131/172.25.196.66/g&quot; `grep 192.168.2.131 -rl ./*`</span><br><span class="line">sed -i &quot;s/db.tars.com/172.25.196.66/g&quot; `grep db.tars.com -rl ./*`</span><br><span class="line">chmod u+x exec-sql.sh</span><br><span class="line">./exec-sql.sh</span><br></pre></td></tr></table></figure>

<p>14、打包框架基础服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt/thirdparty/tars-1.5.0/cpp/build/</span><br><span class="line">make framework-tar</span><br><span class="line"></span><br><span class="line">make tarsstat-tar</span><br><span class="line">make tarsnotify-tar</span><br><span class="line">make tarsproperty-tar</span><br><span class="line">make tarslog-tar</span><br><span class="line">make tarsquerystat-tar</span><br><span class="line">make tarsqueryproperty-tar</span><br></pre></td></tr></table></figure>

<p>15、安装核心基础服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /usr/local/app/tars/</span><br><span class="line">cd /mnt/thirtyparty/tars-1.5.0/cpp/build</span><br><span class="line"></span><br><span class="line">cp framework.tgz /usr/local/app/tars/</span><br><span class="line">cd /usr/local/app/tars</span><br><span class="line">tar xf framework.tgz</span><br><span class="line"></span><br><span class="line">sed -i &quot;s/192.168.2.131/172.25.196.66/g&quot; `grep 192.168.2.131 -rl ./*`</span><br><span class="line">sed -i &quot;s/db.tars.com/172.25.196.66/g&quot; `grep db.tars.com -rl ./*`</span><br><span class="line">sed -i &quot;s/registry.tars.com/172.25.196.66/g&quot; `grep registry.tars.com -rl ./*`</span><br><span class="line">sed -i &quot;s/web.tars.com/172.25.196.66/g&quot; `grep web.tars.com -rl ./*`</span><br><span class="line"></span><br><span class="line">chmod u+x tars_install.sh</span><br><span class="line">./tars_install.sh</span><br><span class="line">./tarspatch/util/init.sh</span><br></pre></td></tr></table></figure>

<p>16、安装web管理系统</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">cd /mnt/thirtparty/tars-1.5.0/web/</span><br><span class="line">sed -i &quot;s/db.tars.com/172.25.196.66/g&quot; `grep db.tars.com -rl ./src/main/resources/*`</span><br><span class="line">sed -i &quot;s/registry1.tars.com/172.25.196.66/g&quot; `grep registry1.tars.com -rl ./src/main/resources/*`</span><br><span class="line">sed -i &quot;s/registry2.tars.com/172.25.196.66/g&quot; `grep registry2.tars.com -rl ./src/main/resources/*`</span><br><span class="line"></span><br><span class="line">mvn clean package</span><br><span class="line">cp ./target/tars.war /usr/local/resin/webapps/</span><br><span class="line">#./web/target/tars/WEB-INF/classes/log4j.properties  这里可以修改日志目录</span><br><span class="line">mkdir -p /data/log/tars/</span><br><span class="line">mv /usr/local/resin/conf/resin.xml /usr/local/resin/conf/resin.xml.backup</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br></pre></td><td class="code"><pre><span class="line">cat &gt; /usr/local/resin/conf/resin.xml &lt;&lt; EOF</span><br><span class="line">&lt;!--</span><br><span class="line">   - Resin 4.0 configuration file.</span><br><span class="line">  --&gt;</span><br><span class="line">&lt;resin xmlns=&quot;http://caucho.com/ns/resin&quot;</span><br><span class="line">       xmlns:resin=&quot;urn:java:com.caucho.resin&quot;&gt;</span><br><span class="line"></span><br><span class="line">  &lt;!-- property-based Resin configuration --&gt;</span><br><span class="line">  &lt;resin:properties path=&quot;\$&#123;__DIR__&#125;/resin.properties&quot; optional=&quot;true&quot;/&gt;</span><br><span class="line"></span><br><span class="line">  &lt;resin:if test=&quot;\$&#123;properties_import_url&#125;&quot;&gt;</span><br><span class="line">     &lt;resin:properties path=&quot;\$&#123;properties_import_url&#125;&quot;</span><br><span class="line">                    optional=&quot;true&quot; recover=&quot;true&quot;/&gt;</span><br><span class="line">  &lt;/resin:if&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  &lt;!-- Logging configuration for the JDK logging API --&gt;</span><br><span class="line">  &lt;log-handler name=&quot;&quot; level=&quot;all&quot; path=&quot;stdout:&quot;</span><br><span class="line">               timestamp=&quot;[%y-%m-%d %H:%M:%S.%s]&quot;</span><br><span class="line">               format=&quot; &#123;\$&#123;thread&#125;&#125; \$&#123;log.message&#125;&quot;/&gt;</span><br><span class="line">               </span><br><span class="line">  &lt;!--</span><br><span class="line">     - Alternative pseudo-TTCC log format</span><br><span class="line">     -</span><br><span class="line">     - &lt;log-handler name=&quot;&quot; level=&quot;all&quot; path=&quot;stdout:&quot;</span><br><span class="line">     -           timestamp=&quot;%y-%m-%d %H:%M:%S.%s&quot;</span><br><span class="line">     -           format=&quot; [\$&#123;thread&#125;] \$&#123;log.level&#125; \$&#123;log.shortName&#125; - \$&#123;log.message&#125;&quot;/&gt;</span><br><span class="line">    --&gt;</span><br><span class="line">   </span><br><span class="line">  &lt;!--</span><br><span class="line">     - level=&apos;info&apos; for production</span><br><span class="line">     - &apos;fine&apos; or &apos;finer&apos; for development and troubleshooting</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;logger name=&quot;&quot; level=&quot;\$&#123;log_level?:&apos;info&apos;&#125;&quot;/&gt;</span><br><span class="line"></span><br><span class="line">  &lt;logger name=&quot;com.caucho.java&quot; level=&quot;config&quot;/&gt;</span><br><span class="line">  &lt;logger name=&quot;com.caucho.loader&quot; level=&quot;config&quot;/&gt;</span><br><span class="line"></span><br><span class="line">  &lt;!--</span><br><span class="line">     - Default configuration applied to all clusters, including</span><br><span class="line">     - HTTP, HTTPS, and /resin-admin configuration.</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;resin:import path=&quot;\$&#123;__DIR__&#125;/cluster-default.xml&quot;/&gt;</span><br><span class="line"> </span><br><span class="line">  &lt;!--</span><br><span class="line">     - health configuration</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;resin:import path=&quot;\$&#123;__DIR__&#125;/health.xml&quot;/&gt;</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">  &lt;!--</span><br><span class="line">     - Remote management requires at least one enabled admin user.</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;resin:AdminAuthenticator&gt;</span><br><span class="line">    &lt;user name=&quot;\$&#123;admin_user&#125;&quot; password=&quot;\$&#123;admin_password&#125;&quot;/&gt;</span><br><span class="line">    </span><br><span class="line">    &lt;resin:import path=&quot;\$&#123;__DIR__&#125;/admin-users.xml&quot; optional=&quot;true&quot;/&gt;</span><br><span class="line">  &lt;/resin:AdminAuthenticator&gt;</span><br><span class="line"></span><br><span class="line">  &lt;!--</span><br><span class="line">     - For clustered systems, create a password in as cluster_system_key</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;cluster-system-key&gt;\$&#123;cluster_system_key&#125;&lt;/cluster-system-key&gt;</span><br><span class="line"></span><br><span class="line">  &lt;!--</span><br><span class="line">     - For production sites, change dependency-check-interval to something</span><br><span class="line">     - like 600s, so it only checks for updates every 10 minutes.</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;dependency-check-interval&gt;\$&#123;dependency_check_interval?:&apos;2s&apos;&#125;&lt;/dependency-check-interval&gt;</span><br><span class="line"></span><br><span class="line">  &lt;!-- For resin.properties dynamic cluster joining --&gt;</span><br><span class="line">  &lt;home-cluster&gt;\$&#123;home_cluster&#125;&lt;/home-cluster&gt;</span><br><span class="line">  &lt;home-server&gt;\$&#123;home_server&#125;&lt;/home-server&gt;</span><br><span class="line">  &lt;elastic-server&gt;\$&#123;elastic_server&#125;&lt;/elastic-server&gt;</span><br><span class="line">  &lt;elastic-dns&gt;\$&#123;elastic_dns&#125;&lt;/elastic-dns&gt;</span><br><span class="line"></span><br><span class="line">  &lt;!--</span><br><span class="line">     - Configures the main application cluster.  Load-balancing configurations</span><br><span class="line">     - will also have a web cluster.</span><br><span class="line">    --&gt;</span><br><span class="line">  &lt;cluster id=&quot;app&quot;&gt;</span><br><span class="line">    &lt;!-- define the servers in the cluster --&gt;</span><br><span class="line">    &lt;server-multi id-prefix=&quot;app-&quot; address-list=&quot;\$&#123;app_servers&#125;&quot; port=&quot;6800&quot;/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;host-default&gt;</span><br><span class="line">      &lt;!-- creates the webapps directory for .war expansion --&gt;</span><br><span class="line">      &lt;web-app-deploy path=&quot;webapps&quot;</span><br><span class="line">                      expand-preserve-fileset=&quot;WEB-INF/work/**&quot;</span><br><span class="line">                      multiversion-routing=&quot;\$&#123;webapp_multiversion_routing&#125;&quot;</span><br><span class="line">                      path-suffix=&quot;\$&#123;elastic_webapp?resin.id:&apos;&apos;&#125;&quot;/&gt;</span><br><span class="line">    &lt;/host-default&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!-- auto virtual host deployment in hosts/foo.example.com/webapps --&gt;</span><br><span class="line">    &lt;host-deploy path=&quot;hosts&quot;&gt;</span><br><span class="line">      &lt;host-default&gt;</span><br><span class="line">        &lt;resin:import path=&quot;host.xml&quot; optional=&quot;true&quot;/&gt;</span><br><span class="line">      &lt;/host-default&gt;</span><br><span class="line">    &lt;/host-deploy&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!-- the default host, matching any host name --&gt;</span><br><span class="line">    &lt;host id=&quot;&quot; root-directory=&quot;.&quot;&gt;</span><br><span class="line">      &lt;!--</span><br><span class="line">         - webapps can be overridden/extended in the resin.xml</span><br><span class="line">        --&gt;</span><br><span class="line">      &lt;web-app id=&quot;/&quot; document-directory=&quot;webapps/tars&quot;/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;/host&gt;</span><br><span class="line">      </span><br><span class="line">    &lt;resin:if test=&quot;\$&#123;resin_doc&#125;&quot;&gt;</span><br><span class="line">      &lt;host id=&quot;\$&#123;resin_doc_host&#125;&quot; root-directory=&quot;\$&#123;resin_doc_host&#125;&quot;&gt;</span><br><span class="line">        &lt;web-app id=&quot;/resin-doc&quot; root-directory=&quot;\$&#123;resin.root&#125;/doc/resin-doc&quot;/&gt;</span><br><span class="line">      &lt;/host&gt;</span><br><span class="line">    &lt;/resin:if&gt;</span><br><span class="line">  &lt;/cluster&gt;</span><br><span class="line"></span><br><span class="line">  &lt;cluster id=&quot;web&quot;&gt;</span><br><span class="line">    &lt;!-- define the servers in the cluster --&gt;</span><br><span class="line">    &lt;server-multi id-prefix=&quot;web-&quot; address-list=&quot;\$&#123;web_servers&#125;&quot; port=&quot;6810&quot;/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;host id=&quot;&quot; root-directory=&quot;web&quot;&gt;</span><br><span class="line">      &lt;web-app id=&quot;&quot;&gt;</span><br><span class="line">        &lt;resin:LoadBalance regexp=&quot;&quot; cluster=&quot;app&quot;/&gt;</span><br><span class="line">      &lt;/web-app&gt;</span><br><span class="line">    &lt;/host&gt;</span><br><span class="line">  &lt;/cluster&gt;</span><br><span class="line"></span><br><span class="line">  &lt;cluster id=&quot;memcached&quot; xmlns:memcache=&quot;urn:java:com.caucho.memcached&quot;&gt;</span><br><span class="line">    &lt;!-- define the servers in the cluster --&gt;</span><br><span class="line">    &lt;server-multi id-prefix=&quot;memcached-&quot; address-list=&quot;\$&#123;memcached_servers&#125;&quot; port=&quot;6820&quot;&gt;</span><br><span class="line">      &lt;!-- listen for the memcache protocol --&gt;</span><br><span class="line">      &lt;listen port=&quot;\$&#123;memcached_port?:11211&#125;&quot;</span><br><span class="line">              keepalive-timeout=&quot;600s&quot; socket-timeout=&quot;600s&quot;&gt;</span><br><span class="line">        &lt;memcache:MemcachedProtocol/&gt;</span><br><span class="line">      &lt;/listen&gt;</span><br><span class="line">    &lt;/server-multi&gt;</span><br><span class="line">  &lt;/cluster&gt;</span><br><span class="line"> </span><br><span class="line">  &lt;cluster id=&quot;proxycache&quot;&gt;</span><br><span class="line">    &lt;!-- define the servers in the cluster --&gt;</span><br><span class="line">    &lt;server-multi id-prefix=&quot;proxycache-&quot; address-list=&quot;\$&#123;proxycache_servers&#125;&quot; port=&quot;6830&quot;/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;host id=&quot;&quot; root-directory=&quot;proxycache&quot;&gt;</span><br><span class="line">      &lt;web-app id=&quot;&quot;&gt;</span><br><span class="line">        &lt;resin:HttpProxy regexp=&quot;.*&quot;&gt;</span><br><span class="line">          &lt;!-- backend HTTP servers to proxy to --&gt;</span><br><span class="line">          &lt;addresses&gt;\$&#123;backend_servers&#125;&lt;/addresses&gt;</span><br><span class="line">        &lt;/resin:HttpProxy&gt;</span><br><span class="line">      &lt;/web-app&gt;</span><br><span class="line">    &lt;/host&gt;</span><br><span class="line">  &lt;/cluster&gt;</span><br><span class="line"></span><br><span class="line">&lt;/resin&gt;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure>

<p>17、现在可以访问8080端口的web管理系统了</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/resin/bin/resin.sh start</span><br></pre></td></tr></table></figure>

<p><a href="http://172.25.196.66:8080" target="_blank" rel="noopener">http://172.25.196.66:8080</a></p>
<img src="/blog/2019/10/25/tars框架环境基础搭建/1.png">



<p>OK   这样一个tencent的微服务架构就搭建完成了！  快来试试吧！tars就先到这里，后续会持续更新其他。。。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/10/20/认识tars框架/">
                认识tars框架
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-10-20</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>###介绍</p>
<p>Tars是【基于名字服务】【使用Tars协议】的高性能【RPC】开发框架，同时配套一体化的【服务治理平台】，帮助个人或者企业快速的以微服务的方式构建自己稳定可靠的分布式应用。</p>
<p>Tars在腾讯内部名为TAF，内部从08年开始使用，到现在将近10个年头了，今年终于开源。目前该框架在腾讯内部，有100多个业务、1.6多万台服务器上运行使用。<br>Tars也是一个兼顾易用性、高性能、服务治理的框架，目的是让开发更简单，聚焦业务逻辑，让运营更高效，一切尽在掌握。</p>
<p>目前，我日常开发也是使用该框架，十分方便快捷，而且配套的服务管理系统，为服务监控、运维到来了很大的便利。</p>
<p>腾讯微服务架构代码地址：<a href="https://github.com/Tencent/Tars" target="_blank" rel="noopener">https://github.com/Tencent/Tars</a></p>
<p>###设计思想</p>
<p>Tars的设计思路是采用微服务的思想对服务进行治理，同时对整个系统的各个模块进行抽象分层，将各个层次之间相互解耦或者松耦合，如下图：</p>
<img src="/blog/2019/10/20/认识tars框架/1.png">

<p>最底的协议层，设计思路是将业务网络通信的协议进行统一，以IDL(接口定义语言)的方式，开发支持多平台、可扩展、【协议代码自动生成】的统一协议。在开发过程中，开发人员只需要关注通讯的协议字段的内容，不需要关注其实现的细节，大大减轻了开发服务时需要考虑的协议是否能跨平台使用、是否可能需要兼容、扩展等问题。</p>
<p>中间的公共库、通讯框架、平台层，设计思路是让业务开发更加聚焦业务逻辑的本身。因此，从使用者的角度出发，封装了大量日常开发过程中经常使用的公共库代码和远程过程调用，让开发使用更简单方便；从框架本身的角度出发，做到高稳定性、高可用性、高性能，这样才能让业务服务运营更加放心；从分布式平台的角度出发，解决服务运营过程中，遇到的容错、负载均衡、容量管理、就近接入、灰度发布等问题，让平台更加强大。</p>
<p>最上面的运营层，设计思路是让运维只需要关注日常的服务部署、发布、配置、监控、调度管理等操作。</p>
<p>###整体架构</p>
<p>####架构拓扑图</p>
<img src="/blog/2019/10/20/认识tars框架/2.png">


<p>整体架构的拓扑图主要分为2个部分：服务节点与公共框架节点。</p>
<p>服务节点:</p>
<p>服务节点可以认为是服务所实际运行的一个具体的操作系统实例，可以是物理主机或者虚拟主机、云主机。随着服务的种类扩展和规模扩大，服务节点可能成千上万甚至数以十万计。<br>每台服务节点上均有一个Node服务节点和N(N&gt;=0)个业务服务节点，Node服务节点会对业务服务节点进行统一管理，提供启停、发布、监控等功能，同时接收业务服务节点上报过来的心跳。</p>
<p>公共框架节点:</p>
<p>除了服务节点以外的服务，其他服务节点均归为一类。</p>
<p>公共框架节点，数量不定，为了自身的容错容灾，一般也要求在在多个机房的多个服务器上进行部署，具体的节点数量，与服务节点的规模有关，比如，如果某些服务需要打较多的日志，就需要部署更多的日志服务节点。</p>
<p>又可细分为如下几个部分：</p>
<p>Web管理系统：在Web上可以看到服务运行的各种实时数据情况，以及对服务进行发布、启停、部署等操作；</p>
<p>Registry（路由+管理服务）：提供服务节点的地址查询、发布、启停、管理等操作，以及对服务上报心跳的管理，通过它实现服务的注册与发现；</p>
<p>Patch（发布管理）：提供服务的发布功能；</p>
<p>Config（配置中心）：提供服务配置文件的统一管理功能；</p>
<p>Log（远程日志）：提供服务打日志到远程的功能；</p>
<p>Stat（调用统计）：统计业务服务上报的各种调用信息，比如总流量、平均耗时、超时率等，以便对服务出现异常时进行告警；</p>
<p>Property（业务属性）：统计业务自定义上报的属性信息，比如内存使用大小、队列大小、cache命中率等，以便对服务出现异常时进行告警；</p>
<p>Notify（异常信息）：统计业务上报的各种异常信息，比如服务状态变跟信息、访问db失败信息等，以便对服务出现异常时进行告警；</p>
<p>原则上要求全部的节点之间网络互通，至少每台机器的node能够与公共框架节点之间都是可以连通的。</p>
<p>####服务交互流程图</p>
<img src="/blog/2019/10/20/认识tars框架/3.png">


<p>框架服务在整个系统中运行时，服务之间的交互分：业务服务之间的交互、业务服务与框架基础服务之间的交互。</p>
<p>服务发布流程：在Web系统上传server的发布包到patch，上传成功后，在web上提交发布server请求，由registry服务传达到node，然后node拉取server的发布包到本地，拉起server服务。</p>
<p>管理命令流程：Web系统上的可以提交管理server服务命令请求，由registry服务传达到node服务，然后由node向server发送管理命令。</p>
<p>心跳上报流程：server服务运行后，会定期上报心跳到node，node然后把服务心跳信息上报到registry服务，由registry进行统一管理。</p>
<p>信息上报流程：server服务运行后，会定期上报统计信息到stat，打印远程日志到log，定期上报属性信息到property、上报异常信息到notify、从config拉取服务配置信息。</p>
<p>Client访问Server流程：client可以通过server的对象名Obj间接访问server(即通过名字服务来路由，而不是写死IP)，Client会从registry上拉取server的路由信息（如ip、port信息），然后根据具体的业务特性（同步或者异步，tcp或者udp方式）访问server(当然client也可以通过ip/port直接访问server)。</p>
<p>####web管理系统</p>
<img src="/blog/2019/10/20/认识tars框架/4.png">


<p>web管理系统主要包含以下功能：</p>
<p>业务管理：包括已部署的服务，以及服务管理、发布管理、服务配置、服务监控、特性监控等；</p>
<p>运维管理：包括服务部署、扩容、模版管理等；</p>
<p>####服务结构图</p>
<p>框架核心的服务端与客户端实现结构图如下:</p>
<img src="/blog/2019/10/20/认识tars框架/5.png">

<p>服务端：</p>
<p>NetThread：网络线程，负责收发包，连接管理，多线程(可配置），采用epoll ET触发实现，支持tcp/udp；</p>
<p>BindAdapter： 绑定端口类，用于管理servent(业务线程)对应的绑定端口的信息操作；</p>
<p>ServantHandle：业务线程类，根据对象名分派Servant的对象和接口调用；</p>
<p>AdminServant： 管理端口的对象；</p>
<p>ServantImp： 继承Servant的业务处理基类（Servent：服务端接口对象的基类）；</p>
<p>客户端：</p>
<p>NetThread：网络线程， 收发包，连接管理，多线程(可配置），采用epoll ET触发实现，支持tcp/udp；</p>
<p>AdapterProxy： 具体服务器某个节点的本地代理，管理到服务器的连接，以及请求超时处理；</p>
<p>ObjectProxy： 远程对象代理，负责路由分发、负载均衡、容错，支持轮询/hash/权重；</p>
<p>ServantProxy： 远程对象调用的本地代理，支持同步/异步/单向，Tars协议和非Tars协议；</p>
<p>AsyncThread： 异步请求的回应包处理线程；</p>
<p>Callback： 具体业务Callback的处理基类对象；</p>
<p>###平台特性</p>
<p>####tars协议</p>
<p>tars协议采用接口描述语言（Interface description language，缩写IDL）来实现，它是一种二进制、可扩展、代码自动生成、支持多平台的协议，使得在不同平台上运行的对象和用不同语言编写的程序可以用PRC远程调用的方式相互通信交流， 主要应用在后台服务之间的网络传输协议，以及对象的序列化和反序列化等方面。</p>
<p>协议支持的类型分两种，基本类型和复杂类型。</p>
<p>基本类型包括：void、bool、byte、short、int、long、float、double、string、unsigned byte、unsigned short、unsigned int；</p>
<p>复杂类型包括：enum、const、struct、vector、map，以及struct、vector、map的嵌套。</p>
<p>例如:</p>
<img src="/blog/2019/10/20/认识tars框架/6.png">

<p>####调用方式</p>
<p>通过IDL语言协议，可以定义服务提供的接口，并自动生成客户端和服务端的相关通信代码，服务端只需实现业务逻辑即可对外提供服务，客户端通过自动生成的代码即可调用服务，调用方式支持三种模式：</p>
<p>同步调用：客户端发出调用请求后等待服务返回结果后再继续逻辑；</p>
<p>异步调用：客户端发出调用请求后继续其他业务逻辑，服务端返回结果又由回调处理类处理结果；</p>
<p>单向调用：客户端发出调用请求后就结束调用，服务端不返回调用结果；</p>
<p>####负载均衡</p>
<p>框架通过名字服务来实现服务的注册与发现，Client通过访问名字服务获取到被调服务的地址信息列表，Client再根据需要选择合适的负载均衡方式来调用服务，负载均衡支持轮询、hash、权重等多种方式。</p>
<img src="/blog/2019/10/20/认识tars框架/7.png">

<p>####容错保护</p>
<p>容错保护通过两种方式实现：名字服务排除和Client主动屏蔽。</p>
<img src="/blog/2019/10/20/认识tars框架/8.png">

<p>名字服务排除的策略：</p>
<p>业务服务主动上报心跳给名字服务，使名字服务知道服务部署的节点存活情况，当服务的某节点故障时，名字服务不在返回故障节点的地址给Client，达到排除故障节点的目标。名字服务排除故障需要通过服务心跳和Client地址列表拉取两个过程，故障排除时间在1分钟左右</p>
<p>Client主动屏蔽：</p>
<p>为了更及时的屏蔽故障节点，Client根据调用被调服务的异常情况来判断是否有故障来更快进行故障屏蔽。具体策略是，当client调用某个svr出现调用连续超时，或者调用的超时比率超过一定百分比，client会对此svr进行屏蔽，让流量分发到正常的节点上去。对屏蔽的svr节点，每隔一定时间进行重连，如果正常，则进行正常的流量分发。</p>
<p>####过载保护</p>
<p>为了防止业务因为访问量突增或服务器故障造成系统整体的繁忙，进而导致全部服务的不可用，框架内部做相应设计来应对。实现请求队列，服务调用通过非阻塞方式实现异步系统，从而达到提升系统处理能力的目的。并且对队列的长度进行监控，当超过某个阀值，则拒绝新的请求。对请求设置超时时间，当请求包从队列里读取出来是判断请求是否超时，如果超时则不做处理。</p>
<img src="/blog/2019/10/20/认识tars框架/9.png">

<p>####消息染色</p>
<p>框架提供了对某服务某接口的特定请求进行染色的能力，染色的消息可以透传到后面需要访问的所有服务上，对染色的请求，服务自动把日志上报到特定的染色日志服务器上，使用者只需在染色服务器上即可分析请求访问的路径，方便跟踪定位问题。<br>如下：</p>
<img src="/blog/2019/10/20/认识tars框架/10.png">

<p>####IDC分组</p>
<p>为了加快服务间的访问速度，建设跨地区、跨机房调用带来的网络资源消耗，减少网络故障带来的影响，框架提供了跨地区、跨机房，就近接入的功能。</p>
<img src="/blog/2019/10/20/认识tars框架/11.png">

<p>####SET分组</p>
<p>为了方便对业务服务部署管理进行标准化和容量化，框架提供了Set部署能力，set之间没有调用关系，互不干扰，故障隔离，提高运维效率和服务可用性。</p>
<img src="/blog/2019/10/20/认识tars框架/12.png">

<p>####数据监控</p>
<p>为了更好反映和监控小到服务进程、大到业务的运行质量情况，框架支持以下数据上报的功能:</p>
<p>1.提供了服务模块间调用信息统计上报的功能，方便用户查看服务的流量、延时、超时、异常等情况；</p>
<img src="/blog/2019/10/20/认识tars框架/13.png">

<p>2.提供了用户自定义属性数据上报的功能，方便用户查看服务的某些纬度或者指标，比如内存使用情况、队列大小、cache命中率等；</p>
<p>3.提供了服务状态变更和异常信息上报的功能，方便用户查看服务的何时发布过、重启过、宕过以及遇到的异常致命错误等；</p>
<p>####集中配置</p>
<p>对业务配置进行集中管理并且操作web化，使配置修改更容易，通知更及时，配置变更也更安全；对配置变更进行历史记录，让配置可以轻松回退到前一版本。配置拉取服务化，服务只需调用配置服务的接口即可获取到配置文件。</p>
<p>为了能灵活管理配置文件，配置文件分为几个级别：应用配置、Set配置、服务配置和节点配置。</p>
<p>应用配置为最高一级的配置文件，它是多个服务配置提炼出来的公共配置，服务配置通过引用它来使用其配置内容。</p>
<p>Set配置是具体一个Set分组下所有服务的公共配置，在应用配置的基础上进行补充追加。</p>
<p>服务配置是具体一个服务下所有节点的公共配置，可以引用应用配置。</p>
<p>节点配置是一个应用节点的个性化配置，它和服务配置合并成为具体一个服务节点的配置。</p>
<p>Tars相关知识就先到这里 ，之后我回发布一篇简单搭建的帖子！后续持续更新！</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/10/05/redis数据迁移备份与恢复/">
                redis数据迁移备份与恢复
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-10-05</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="关于redis数据迁移备份及还原小技巧"><a href="#关于redis数据迁移备份及还原小技巧" class="headerlink" title="关于redis数据迁移备份及还原小技巧"></a>关于redis数据迁移备份及还原小技巧</h1><p>近期部署中遇到需要处理处理rdb文件备份还原，虽然很简单，但是因为之前没用过显得很难受，不敢冒然直接在线上操作，自己做个了小DEMO，测试了下，</p>
<p>首先说<strong>rdb数据备份方法</strong></p>
<p>redis 127.0.0.1:6379&gt; SAVE<br>OK<br>或者命令行直接<br>redis-cli -h 127.0.0.1 -p 6379 -a pwd bgsave<br>该命令将在 redis 安装目录中创建dump.rdb文件。</p>
<p>将文件备份在默认目录下</p>
<p>然后查找dump.rdb文件位置<br>redis 127.0.0.1:6379&gt; CONFIG GET dir<br>1) “dir”<br>2) “/usr/local/redis/bin”<br>以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin。也就是你备份文件的位置，想在哪用自取即可！</p>
<p>使用bgsave也可以<br>创建 redis 备份文件也可以使用命令 BGSAVE，该命令在后台执行。</p>
<p>127.0.0.1:6379&gt; BGSAVE</p>
<p>Background saving started</p>
<p>然后一样去找你的dump.rdb文件位置</p>
<p>当你有了备份，那么你不管回复数据也好还是迁移到其他机器也罢操作都一样</p>
<p>为了区别你的数据可以重命名，然后将你的备份rdb文件放到指定机器或要恢复数据的redis的rdb同级目录，vi 打开你的redis.conf,找到daemonize将no改为yes  默认后台启动避免无法挂载127.0.0.1:6379</p>
<img src="/blog/2019/10/05/redis数据迁移备份与恢复/1.png">

<p>然后配置下面的dbfilename   </p>
<img src="/blog/2019/10/05/redis数据迁移备份与恢复/2.png">



<p>改为你的重命名rdb文件名，或是在目录下替换你的dump.rdb文件，怎么做随你！</p>
<p>然后重启服务并重新加载config文件：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-server redis.conf</span><br></pre></td></tr></table></figure>

<p>然后你的备份数据就恢复了！可能我的办法有点笨拙，如果有不足之处请给为大佬雅正! 其实还有两种方式，你可以自己试一下哦：</p>
<p>另外两种方法：  </p>
<p>1、AOF数据备份恢复方法</p>
<p> 另一种持久化方式AOF，在配置文件中打开[appendonly yes]。 </p>
<p>AOF刷新日志到disk的规则： </p>
<p>appendfsync always #always 表示每次有写操作都进行同步，非常慢，非常安全。 appendfsync everysec #everysec表示对写操作进行累积，每秒同步一次 官方的建议的everysec，安全，就是速度不够快，如果是机器出现问题可能会丢失1秒的数据。 </p>
<p> 也可以手动执行bgrewriteaof进行AOF备份： redis-cli -h 127.0.0.1 -p 6379 -a pwd bgrewriteaof  </p>
<p>迁移数据恢复 迁移到另外一台恢复数据，需先检查配置文件，将按照以下优先级恢复数据到内存： 如果只配置AOF,重启时加载AOF文件恢复数据； 如果同时 配置了RBD和AOF,启动是只加载AOF文件恢复数据； 如果只配置RBD,启动是讲加载dump文件恢复数据；  dump.rdb或者AOF文件迁移到另外一台恢复数据 恢复数据，只需将备份文件 (dump.rdb或者AOF文件) 移动到 redis 安装目录并启动服务即可。  </p>
<p>2、 挂redis从库复制数据方法 </p>
<p>Redis提供了复制（replication）功能可以自动实现同步的过程。</p>
<p>配置方法：</p>
<p> 通过配置文件 从数据库的配置文件中加入slaveof master-ip master-port，主数据库无需配置 通过命令行参数 启动redis-server的时候，</p>
<p>使用命令行参数–slaveof master-ip master port redis-server –port 6380 –slaveof 127.0.0.1 6379 </p>
<p>通过命令SLAVEOF master-ip master-port redis&gt;SLAVEOF 127.0.0.1 6379 SLAVEOF NO ONE可以是当前数据库停止接收其他数据库的同步，转成主Redis数据库，程序连接地址都改为新的redis库IP地址和端口。 </p>
<p>OK 就这些，其他的后续更新！</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/21/负载均衡的5种策略/">
                负载均衡的5种策略
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-21</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>1.轮询（默认）<br>每个请求按时间顺序逐一分配到不同的后端服务器，如果后端服务器down掉，能自动剔除。 </p>
<p>2、指定权重</p>
<p>指定轮询几率，weight和访问比率成正比，用于后端服务器性能不均的情况。 </p>
<p>3、IP绑定 ip_hash</p>
<p>每个请求按访问ip的hash结果分配，这样每个访客固定访问一个后端服务器，可以解决session的问题。</p>
<p>4、fair（第三方）</p>
<p>按后端服务器的响应时间来分配请求，响应时间短的优先分配。 </p>
<p>5、url_hash（第三方）</p>
<p>按访问url的hash结果来分配请求，使每个url定向到同一个后端服务器，后端服务器为缓存时比较有效。 </p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/20/FastDFS结合FastDHT实现文件去重存储/">
                FastDFS结合FastDHT实现文件去重存储
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-20</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h2 id="FastDFS"><a href="#FastDFS" class="headerlink" title="FastDFS"></a>FastDFS</h2><p>FastDFS是一个开源的轻量级<a href="https://baike.baidu.com/item/%E5%88%86%E5%B8%83%E5%BC%8F%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/1250388" target="_blank" rel="noopener">分布式文件系统</a>，它对文件进行管理，功能包括：文件存储、文件同步、文件访问（文件上传、文件下载）等，解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务，如相册网站、视频网站等等。 </p>
<p>FastDFS服务端有两个角色：跟踪器（tracker）和存储<a href="https://baike.baidu.com/item/%E8%8A%82%E7%82%B9" target="_blank" rel="noopener">节点</a>（storage）。跟踪器主要做调度工作，storage主要负责存储。</p>
<h2 id="上传交互过程"><a href="#上传交互过程" class="headerlink" title="上传交互过程"></a>上传交互过程</h2><ol>
<li>client询问tracker上传到的storage，不需要附加参数；</li>
<li>tracker返回一台可用的storage；</li>
<li>client直接和storage通讯完成文件上传。</li>
</ol>
<h2 id="下载交互过程"><a href="#下载交互过程" class="headerlink" title="下载交互过程"></a>下载交互过程</h2><ol>
<li>client询问tracker下载文件的storage，参数为文件标识（卷名和文件名）；</li>
<li>tracker返回一台可用的storage；</li>
<li>client直接和storage通讯完成文件下载。</li>
</ol>
<p>需要说明的是，client为使用FastDFS服务的调用方，client也应该是一台服务器，它对tracker和storage的调用均为服务器间的调用。</p>
<h2 id="FastDHT"><a href="#FastDHT" class="headerlink" title="FastDHT"></a>FastDHT</h2><p><strong>FastDFS本身不能对上传文件进行去重，但支持文件的排重处理机制，所以需要redis类的可以做缓存的数据库做介质或FastDHT作为文件hash的索引存储。FastDHT是FastDFS同一个作者的开源key-value数据库。</strong>其排重原理为：</p>
<h4 id="原理："><a href="#原理：" class="headerlink" title="原理："></a><strong>原理：</strong></h4><p><strong>FastDFS的storage server每次上传均计算文件的hash值，然后从FastDHT服务器上进行查找比对，如果没有返回，则写入hash，并将文件保存；如果有返回，则建立一个新的文件链接（软链），不保存文件。</strong></p>
<h5 id="Ps"><a href="#Ps" class="headerlink" title="Ps:"></a><strong>Ps:</strong></h5><p>​    <strong>注意</strong>：需要说明的是，FastDFS不会返回原始文件的索引，返回的全部都是软链接，当所有的软链接都被删除的时候，原始文件也会从FastDFS中被删除。 </p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/19/关于正向代理和反向代理的理解/">
                关于正向代理和反向代理的理解
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-19</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p><strong>反向代理</strong>和<strong>正向代理</strong>的<strong>区别</strong>就是：</p>
<p>​    正向代理代理客户端，反向代理代理服务器。</p>
<p><strong>反向代理：</strong></p>
<p>​    　反向代理，其实客户端对代理是无感知的，因为客户端不需要任何配置就可以访问，我们只需要将请求发送到反向代理服务器，由反向代理服务器去选择目标服务器获取数据后，在返回给客户端，此时反向代理服务器和目标服务器对外就是一个服务器，暴露的是代理服务器地址，隐藏了真实服务器IP地址。</p>
<img src="/blog/2019/09/19/关于正向代理和反向代理的理解/反向代理.png">

<p><strong>负载均衡</strong>，通过反向代理服务器来优化网站的负载 </p>
<img src="/blog/2019/09/19/关于正向代理和反向代理的理解/nginx反向代理.png">

<p><strong>正向代理：</strong></p>
<p>​    正向代理，意思是一个位于客户端和原始服务器(origin server)之间的服务器，为了从原始服务器取得内容，客户端向代理发送一个请求并指定目标(原始服务器)，然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。</p>
<img src="/blog/2019/09/19/关于正向代理和反向代理的理解/正向代理.png">
        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/18/关于mysql主从热备数据同步的理解/">
                关于mysql主从热备数据同步的理解
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-18</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p><strong>概念：</strong></p>
<p>​    高负载高并发环境下，数据业务层、数据访问层，如果还是传统的数据结构，或者只是单单靠一台服务器负载，如此多的数据库连接操作，数据库必然会崩溃，数据库如果宕机的话，后果更是不堪设想。这时候，我们会考虑如何减少数据库的连接，一方面采用优秀的代码框架，进行代码的优化，采用优秀的数据缓存技术如：redis,如果资金丰厚的话，必然会想到架设MySQL服务集群，来分担主数据库的压力。今天我们利用MySQL主从配置，实现读写分离，减轻数据库压力。</p>
<p>MySQL主从同步的<strong>原理</strong>很简单：</p>
<p>从库生成两个线程，一个I/O线程，一个SQL线程；</p>
<p>I/O 线程，去请求主库 的binlog（二进制日志），并将得到的binlog日志写入到relay log（中继日志） 文件中；主库会生成一个 log dump 线程，用来给从库I/O线程传binlog；</p>
<p>SQL 线程，会读取relay log文件中的日志，并解析成具体操作，来实现主从的操作一致，而最终数据一致。</p>
<p><strong>图解</strong>：</p>
<img src="/blog/2019/09/18/关于mysql主从热备数据同步的理解/mysql主从.png">

<h3 id="关于binlog日志"><a href="#关于binlog日志" class="headerlink" title="关于binlog日志"></a>关于binlog日志</h3><p>binlog是二进制日志文件，用于记录mysql的数据更新或者潜在更新(比如DELETE语句执行删除而实际并没有符合条件的数据)</p>
<p>binlog索引文件mysql-bin.index。如官方文档中所写，binlog格式如下：</p>
<p>binlog文件以一个值为0Xfe62696e的魔数开头，这个魔数对应0xfe ‘b’’i’’n’。</p>
<p>binlog由一系列的binlog event构成。每个binlog event包含header和data两部分。</p>
<p>header部分提供的是event的公共的类型信息，包括event的创建时间，服务器等等。</p>
<p>data部分提供的是针对该event的具体信息，如具体数据的修改。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/15/你真的了解Python内存管理机制吗？/">
                你真的了解Python内存管理机制吗？
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-15</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="python-内存管理机制"><a href="#python-内存管理机制" class="headerlink" title="python 内存管理机制"></a>python 内存管理机制</h1><h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>python 采用的是<strong>引用计数</strong>和<strong>垃圾回收</strong>进行内存管理</p>
<h3 id="垃圾回收机制"><a href="#垃圾回收机制" class="headerlink" title="垃圾回收机制"></a>垃圾回收机制</h3><p>python 采用的是<strong>引用计数</strong>机制为主，<strong>标记-清除</strong>和<strong>分代收集</strong>两种机制为辅的策略。</p>
<h3 id="引用计数"><a href="#引用计数" class="headerlink" title="引用计数"></a>引用计数</h3><ul>
<li>Python语言默认采用的垃圾收集机制是『引用计数法 <code>Reference Counting</code>』，该算法最早George E. Collins在1960的时候首次提出，50年后的今天，该算法依然被很多编程语言使用。</li>
<li>『引用计数法』的原理是：每个对象维护一个<code>ob_ref</code>字段，用来记录该对象当前被引用的次数，每当新的引用指向该对象时，它的引用计数<code>ob_ref</code>加<code>1</code>，每当该对象的引用失效时计数<code>ob_ref</code>减<code>1</code>，一旦对象的引用计数为<code>0</code>，该对象立即被回收，对象占用的内存空间将被释放。</li>
<li>它的缺点是需要额外的空间维护引用计数，这个问题是其次的，不过最主要的问题是它不能解决对象的“循环引用”，因此，也有很多语言比如Java并没有采用该算法做来垃圾的收集机制。</li>
</ul>
<h3 id="引用计数案例"><a href="#引用计数案例" class="headerlink" title="引用计数案例"></a>引用计数案例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">import sys</span><br><span class="line">class A():</span><br><span class="line">    def __init__(self):</span><br><span class="line">        &apos;&apos;&apos;初始化对象&apos;&apos;&apos;</span><br><span class="line">        print(&apos;object born id:%s&apos; %str(hex(id(self))))</span><br><span class="line"></span><br><span class="line">def f1():</span><br><span class="line">    &apos;&apos;&apos;循环引用变量与删除变量&apos;&apos;&apos;</span><br><span class="line">    while True:</span><br><span class="line">        c1=A()</span><br><span class="line">        del c1</span><br><span class="line"></span><br><span class="line">def func(c):</span><br><span class="line">    print(&apos;obejct refcount is: &apos;,sys.getrefcount(c)) #getrefcount()方法用于返回对象的引用计数</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ == &apos;__main__&apos;:</span><br><span class="line">   #生成对象</span><br><span class="line">    a=A()</span><br><span class="line">    func(a)</span><br><span class="line"></span><br><span class="line">    #增加引用</span><br><span class="line">    b=a</span><br><span class="line">    func(a)</span><br><span class="line"></span><br><span class="line">    #销毁引用对象b</span><br><span class="line">    del b</span><br><span class="line">    func(a)</span><br></pre></td></tr></table></figure>

<p>执行结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">object born id:0x265c56a56d8</span><br><span class="line">obejct refcount is:  4</span><br><span class="line">obejct refcount is:  5</span><br><span class="line">obejct refcount is:  4</span><br></pre></td></tr></table></figure>

<h4 id="导致引用计数-1的情况"><a href="#导致引用计数-1的情况" class="headerlink" title="导致引用计数+1的情况"></a>导致引用计数+1的情况</h4><ul>
<li>对象被创建，例如a=23</li>
<li>对象被引用，例如b=a</li>
<li>对象被作为参数，传入到一个函数中，例如<code>func(a)</code></li>
<li>对象作为一个元素，存储在容器中，例如<code>list1=[a,a]</code></li>
</ul>
<h4 id="导致引用计数-1的情况-1"><a href="#导致引用计数-1的情况-1" class="headerlink" title="导致引用计数-1的情况"></a>导致引用计数-1的情况</h4><ul>
<li>对象的别名被显式销毁，例如<code>del a</code></li>
<li>对象的别名被赋予新的对象，例如<code>a=24</code></li>
<li>一个对象离开它的作用域，例如f函数执行完毕时，<code>func</code>函数中的局部变量（全局变量不会）</li>
<li>对象所在的容器被销毁，或从容器中删除对象</li>
</ul>
<h3 id="循环引用导致内存泄露"><a href="#循环引用导致内存泄露" class="headerlink" title="循环引用导致内存泄露"></a>循环引用导致内存泄露</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">def f2():</span><br><span class="line">    &apos;&apos;&apos;循环引用&apos;&apos;&apos;</span><br><span class="line">    while True:</span><br><span class="line">        c1=A()</span><br><span class="line">        c2=A()</span><br><span class="line">        c1.t=c2</span><br><span class="line">        c2.t=c1</span><br><span class="line">        del c1</span><br><span class="line">        del c2</span><br></pre></td></tr></table></figure>

<p>执行结果</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">id:0x1feb9f691d0</span><br><span class="line">object born id:0x1feb9f69438</span><br><span class="line">object born id:0x1feb9f690b8</span><br><span class="line">object born id:0x1feb9f69d68</span><br><span class="line">object born id:0x1feb9f690f0</span><br><span class="line">object born id:0x1feb9f694e0</span><br><span class="line">object born id:0x1feb9f69f60</span><br><span class="line">object born id:0x1feb9f69eb8</span><br><span class="line">object born id:0x1feb9f69128</span><br><span class="line">object born id:0x1feb9f69c88</span><br><span class="line">object born id:0x1feb9f69470</span><br><span class="line">object born id:0x1feb9f69e48</span><br><span class="line">object born id:0x1feb9f69ef0</span><br><span class="line">object born id:0x1feb9f69dd8</span><br><span class="line">object born id:0x1feb9f69e10</span><br><span class="line">object born id:0x1feb9f69ac8</span><br><span class="line">object born id:0x1feb9f69198</span><br><span class="line">object born id:0x1feb9f69cf8</span><br><span class="line">object born id:0x1feb9f69da0</span><br><span class="line">object born id:0x1feb9f69c18</span><br><span class="line">object born id:0x1feb9f69d30</span><br><span class="line">object born id:0x1feb9f69ba8</span><br><span class="line">...</span><br></pre></td></tr></table></figure>

<ul>
<li>创建了<code>c1</code>，<code>c2</code>后，这两个对象的引用计数都是<code>1</code>，执行<code>c1.t=c2</code>和<code>c2.t=c1</code>后，引用计数变成<code>2</code>.</li>
<li>在<code>del c1</code>后，内存<code>c1</code>的对象的引用计数变为<code>1</code>，由于不是为<code>0</code>，所以<code>c1</code>的对象不会被销毁,同理，在<code>del c2</code>后也是一样的。</li>
<li>虽然它们两个的对象都是可以被销毁的，但是由于循环引用，导致垃圾回收器都不会回收它们，所以就会导致内存泄露。</li>
</ul>
<h3 id="分代回收"><a href="#分代回收" class="headerlink" title="分代回收"></a>分代回收</h3><ul>
<li>分代回收是一种以空间换时间的操作方式，Python将内存根据对象的存活时间划分为不同的集合，每个集合称为一个代，Python将内存分为了3“代”，分别为年轻代（第0代）、中年代（第1代）、老年代（第2代），他们对应的是3个链表，它们的垃圾收集频率与对象的存活时间的增大而减小。</li>
<li>新创建的对象都会分配在<strong>年轻代</strong>，年轻代链表的总数达到上限时，Python垃圾收集机制就会被触发，把那些可以被回收的对象回收掉，而那些不会回收的对象就会被移到<strong>中年代</strong>去，依此类推，<strong>老年代</strong>中的对象是存活时间最久的对象，甚至是存活于整个系统的生命周期内。</li>
<li>同时，分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象</li>
</ul>
<h3 id="垃圾回收"><a href="#垃圾回收" class="headerlink" title="垃圾回收"></a>垃圾回收</h3><p>有三种情况会触发垃圾回收：</p>
<ol>
<li>调用<code>gc.collect()</code>,需要先导入<code>gc</code>模块。</li>
<li>当<code>gc</code>模块的计数器达到阀值的时候。</li>
<li>程序退出的时候。</li>
</ol>
<h4 id="gc模块"><a href="#gc模块" class="headerlink" title="gc模块"></a>gc模块</h4><p>gc模块提供一个接口给开发者设置垃圾回收的选项。上面说到，采用引用计数的方法管理内存的一个缺陷是循环引用，而gc模块的一个主要功能就是解决循环引用的问题。</p>
<p><strong>常用函数</strong>：</p>
<ol>
<li><code>gc.set_debug(flags)</code> 设置gc的debug日志，一般设置为<code>gc.DEBUG_LEAK</code></li>
<li><code>gc.collect([generation])</code><br>显式进行垃圾回收，可以输入参数，<code>0</code>代表只检查第一代的对象，<code>1</code>代表检查一，二代的对象，<code>2</code>代表检查一，二，三代的对象，如果不传参数，执行一个<code>full collection</code>，也就是等于传2。返回不可达（unreachable objects）对象的数目。</li>
<li><code>gc.set_threshold(threshold0[, threshold1[, threshold2])</code><br>设置自动执行垃圾回收的频率。</li>
<li><code>gc.get_count()</code> 获取当前自动执行垃圾回收的计数器，返回一个长度为3的列表</li>
</ol>
<p>扩展资料：<a href="https://docs.python.org/3.5/library/gc.html" target="_blank" rel="noopener">Garbage Collector interface</a></p>
<h4 id="gc实践案例"><a href="#gc实践案例" class="headerlink" title="gc实践案例"></a>gc实践案例</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">def f3():</span><br><span class="line">    &apos;&apos;&apos;循环引用&apos;&apos;&apos;</span><br><span class="line">    while True:</span><br><span class="line">        c1=A()</span><br><span class="line">        c2=A()</span><br><span class="line">        c1.t=c2</span><br><span class="line">        c2.t=c1</span><br><span class="line">        del c1</span><br><span class="line">        del c2</span><br><span class="line">        #增加垃圾回收机制</span><br><span class="line">        print(gc.garbage)</span><br><span class="line">        print(gc.collect())</span><br><span class="line">        print(gc.garbage)</span><br><span class="line">        time.sleep(10)</span><br></pre></td></tr></table></figure>

<p>执行结果</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">object born id:0x21d1a5dc470</span><br><span class="line">object born id:0x21d1a5dc9e8</span><br><span class="line">[]</span><br><span class="line">4</span><br><span class="line">gc: collectable &lt;A 0x0000021D1A5DC470&gt;</span><br><span class="line">[&lt;__main__.A object at 0x0000021D1A5DC470&gt;, &lt;__main__.A object at 0x0000021D1A5DC9E8&gt;, &#123;&apos;t&apos;: &lt;__main__.A object at 0x0000021D1A5DC9E8&gt;&#125;, &#123;&apos;t&apos;: &lt;__main__.A object at 0x0000021D1A5DC470&gt;&#125;]</span><br><span class="line">gc: collectable &lt;A 0x0000021D1A5DC9E8&gt;</span><br><span class="line">gc: collectable &lt;dict 0x0000021D1A156C88&gt;</span><br><span class="line">gc: collectable &lt;dict 0x0000021D1A5CABC8&gt;</span><br></pre></td></tr></table></figure>

<h3 id="gc模块的自动垃圾回收机制"><a href="#gc模块的自动垃圾回收机制" class="headerlink" title="gc模块的自动垃圾回收机制"></a>gc模块的自动垃圾回收机制</h3><p>必须要import gc模块，并且is_enable()=True才会启动自动垃圾回收。<br>这个机制的主要作用就是发现并处理不可达的垃圾对象。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">垃圾回收=垃圾检查+垃圾回收</span><br></pre></td></tr></table></figure>

<p>在Python中，采用分代收集的方法。把对象分为三代，一开始，对象在创建的时候，放在一代中，如果在一次一代的垃圾检查中，改对象存活下来，就会被放到二代中，同理在一次二代的垃圾检查中，该对象存活下来，就会被放到三代中。</p>
<p>gc模块里面会有一个长度为3的列表的计数器，可以通过<code>gc.get_count()</code>获取。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">def f4():</span><br><span class="line">    &apos;&apos;&apos;垃圾自动回收&apos;&apos;&apos;</span><br><span class="line">    print(gc.get_count())</span><br><span class="line">    a=A()</span><br><span class="line">    print(gc.get_count())</span><br><span class="line">    del a</span><br><span class="line">    print(gc.get_count())</span><br></pre></td></tr></table></figure>

<p>执行结果</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">(621, 10, 0)</span><br><span class="line">object born id:0x2ca32a8c588</span><br><span class="line">(624, 10, 0)</span><br><span class="line">(623, 10, 0)</span><br></pre></td></tr></table></figure>

<ul>
<li><code>621</code>指距离上一次<code>一代</code>垃圾检查，Python分配内存的数目减去释放内存的数目，注意:是内存分配，而不是引用计数的增加。</li>
<li><code>10</code>指距离上一次<code>二代</code>垃圾检查，<code>一代</code>垃圾检查的次数。</li>
<li><code>0</code>是指距离上一次<code>三代</code>垃圾检查，<code>二代</code>垃圾检查的次数。</li>
</ul>
<h3 id="自动回收阈值"><a href="#自动回收阈值" class="headerlink" title="自动回收阈值"></a>自动回收阈值</h3><p>gc模快有一个自动垃圾回收的阀值，即通过<code>gc.get_threshold</code>函数获取到的长度为3的元组，例如<code>(700,10,10)</code><br>每一次计数器的增加，gc模块就会检查增加后的计数是否达到阀值的数目，如果是，就会执行对应的代数的垃圾检查，然后重置计数器</p>
<p>注意：<br>如果循环引用中，两个对象都定义了<code>__del__</code>方法，gc模块不会销毁这些不可达对象，因为gc模块不知道应该先调用哪个对象的<code>__del__</code>方法，所以为了安全起见，gc模块会把对象放到<code>gc.garbage</code>中，但是不会销毁对象。</p>
<h3 id="标记清除"><a href="#标记清除" class="headerlink" title="标记清除"></a>标记清除</h3><p>标记清除（Mark—Sweep）』算法是一种基于追踪回收（tracing GC）技术实现的垃圾回收算法。它分为两个阶段：第一阶段是标记阶段，GC会把所有的『活动对象』打上标记，第二阶段是把那些没有标记的对象『非活动对象』进行回收。那么GC又是如何判断哪些是活动对象哪些是非活动对象的呢？</p>
<p><a href="https://sutune.oss-cn-shenzhen.aliyuncs.com/python/GC/mark-sweep.svg" target="_blank" rel="noopener"><img src="https://sutune.oss-cn-shenzhen.aliyuncs.com/python/GC/mark-sweep.svg" alt="image"></a></p>
<p>对象之间通过引用（指针）连在一起，构成一个有向图，对象构成这个有向图的节点，而引用关系构成这个有向图的边。从根对象（root object）出发，沿着有向边遍历对象，可达的（reachable）对象标记为活动对象，不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。 mark-sweepg 在上图中，我们把小黑圈视为全局变量，也就是把它作为root object，从小黑圈出发，对象1可直达，那么它将被标记，对象2、3可间接到达也会被标记，而4和5不可达，那么1、2、3就是活动对象，4和5是非活动对象会被GC回收。</p>
<p>标记清除算法作为Python的辅助垃圾收集技术主要处理的是一些容器对象，比如list、dict、tuple，instance等，因为对于字符串、数值对象是不可能造成循环引用问题。Python使用一个双向链表将这些容器对象组织起来。不过，这种简单粗暴的标记清除算法也有明显的缺点：清除非活动的对象前它必须顺序扫描整个堆内存，哪怕只剩下小部分活动对象也要扫描所有对象。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/13/三次握手四次挥手详解/">
                三次握手四次挥手详解
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-13</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="TCP三次握手及四次挥手及常见问题详解"><a href="#TCP三次握手及四次挥手及常见问题详解" class="headerlink" title="TCP三次握手及四次挥手及常见问题详解"></a>TCP三次握手及四次挥手及常见问题详解</h1><p>TCP的报头：<img src="https://img-blog.csdn.net/20180524114307959?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1pXRTc2MTYxNzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="这里写图片描述"></p>
<p>源端口号：表示发送端端口号，字段长为16位。<br>目标端口号：表示接收端口号，字段长为16位。<br>序列号：表示发送数据的位置，字段长为32位。每发送一次数据，就累加一次该数据字节数的大小。<br>注意：序列号不会从0或1开始，而是在建立连接时由计算机生成的一个随机数作为其初始值，通过SYN包发送给接收端主机。然后再将每转发过去的字节数累加到初始值上表示数据的位置。<br>确认应答号：表示下一次应该收到的数据的序列号，字段长为32字节。发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。<br>序号的优点：<br>（1）保证报文按序到达。<br>（2）保证可靠性。<br>（3）保证效率。<br>（4）精准的报告哪些报文已经收到，哪些需要重传。</p>
<p>首部长度：该字段长度为4位，单位为4字节（32位）。TCP首部长度不包括选项的话，是20个字节，20/4=5，5的二进制序列：0101，报头长度也叫数据偏移，所以该字段可以设置为5，选项字段最大的是40字节，所以，TCP首部长度为最大为20+40=60字节，该字段可以设置的最大长度为60/4=15。<br>保留：该字段主要是为了以后扩展时使用，其长度为4位。一般设置为0，即使收到的包在该字段不为0，此包也不会丢弃。<br>控制位：字段长为6，每一位从左到右分别为：URG、ACK、PSH、RST、SYN、FIN。当对应的值为1，表示有具体含义。<br>字段|含义<br>—|:—<br>URG|紧急指针是否有效。为1，表示某一位需要被优先处理。<br>ACK|确认号是否有效，一般置为1。<br>PSH|提示接收端应用程序立即从TCP缓冲区把数据读走。<br>RST|对方要求重新建立连接，复位。<br>SYN|请求建立连接，并在其序列号的字段进行序列号的初始值设定。建立连接，设置为1.<br>FIN|希望断开连接。<br>窗口大小：接收缓冲区的大小，TCP不允许发送超过此处所示大小的数据。<br>校验和：发送端填充，CRC校验，接收校验不通过，则认为数据有问题。和UDP的区别是，UDP校验的是数据本身，TCP校验的不仅包含TCP首部，而且包含TCP数据部分。<br>紧急指针：只有在URG为1时有效，该字段为1表示本报文的段中的紧急数据的指针。<br>选项：用于提高TCP的传输性能。需要根据首部长度进行控制，其最大长度为40字节。<br>我们在着重讲一下在三次握手和四次挥手中的用到序列号、确认号及标志位。</p>
<ol>
<li><p>序列号seq<br>占4个字节，用来标记数据段的顺序，TCP把连接中发送的所有数据字节都编上一个序号，第一个字节的编号由本地随机产生，给字节编上序号后，就给每一个报文段指派一个序号，序列号seq就是这个报文段中的第一个字节的数据编号。</p>
</li>
<li><p>确认号ack<br>占4个字节，期待收到对方下一个报文段的第一个数据字节的序号，序列号表示报文段携带数据的第一个字节的编号，而确认号指的是期望接受到下一个字节的编号，因此挡墙报文段最后一个字节的编号+1即是确认号。</p>
</li>
<li><p>确认ACK</p>
</li>
</ol>
<p>占1个比特位，仅当ACK=1，确认号字段才有效。ACK=0，确认号无效。</p>
<ol start="4">
<li><p>同步SYN<br>连接建立时用于同步序号。当SYN=1，ACK=0表示：这是一个连接请求报文段。若同意连接，则在响应报文段中使用SYN=1，ACK=1.因此，SYN=1表示这是一个连接请求，或连接接收报文，SYN这个标志位只有在TCP建立连接才会被置为1，握手完成后SYN标志位被置为0.</p>
</li>
<li><p>终止FIN<br>用来释放一个</p>
</li>
</ol>
<p>TCP三次握手以及四次挥手的过程</p>
<p>三次握手的过程</p>
<p>step1:第一次握手<br>建立连接时，客户端发送SYN包到服务器，其中包含客户端的初始序号seq=x，并进入SYN_SENT状态，等待服务器确认。（其中，SYN=1，ACK=0，表示这是一个TCP连接请求数据报文；序号seq=x，表明传输数据时的第一个数据字节的序号是x）。</p>
<p>step2:第二次握手<br>服务器收到请求后，必须确认客户的数据包。同时自己也发送一个SYN包，即SYN+ACK包，此时服务器进入SYN_RECV状态。（其中确认报文段中，标识位SYN=1，ACK=1，表示这是一个TCP连接响应数据报文，并含服务端的初始序号seq(服务器)=y，以及服务器对客户端初始序号的确认号ack(服务器)=seq(客户端)+1=x+1）。</p>
<p>step3:第三次握手<br>客户端收到服务器的SYN+ACK包，向服务器发送一个序列号(seq=x+1)，确认号为ack(客户端)=y+1，此包发送完毕，客户端和服务器进入ESTAB_LISHED(TCP连接成功)状态，完成三次握手。</p>
<p>未连接队列<br>在三次握手协议中，服务器维护一个未连接队列，该队列为每个客户端的SYN包(syn=j)开设一个条目，该条目表明服务器已收到SYN包，并向客户发出确认，正在等待客户的确认包时，删除该条目，服务器进入ESTAB_LISHED状态。</p>
<p>常见面试题：</p>
<p>1.为什么需要三次握手，两次不可以吗？或者四次、五次可以吗？<br>我们来分析一种特殊情况，假设客户端请求建立连接，发给服务器SYN包等待服务器确认，服务器收到确认后，如果是两次握手，假设服务器给客户端在第二次握手时发送数据，数据从服务器发出，服务器认为连接已经建立，但在发送数据的过程中数据丢失，客户端认为连接没有建立，会进行重传。假设每次发送的数据一直在丢失，客户端一直SYN，服务器就会产生多个无效连接，占用资源，这个时候服务器可能会挂掉。这个现象就是我们听过的“SYN的洪水攻击”。<br>总结：第三次握手是为了防止：如果客户端迟迟没有收到服务器返回确认报文，这时会放弃连接，重新启动一条连接请求，但问题是：服务器不知道客户端没有收到，所以他会收到两个连接，浪费连接开销。如果每次都是这样，就会浪费多个连接开销。</p>
<p>四次挥手过程（关闭客户端到服务器的连接）</p>
<p>step1：第一次挥手<br>首先，客户端发送一个FIN，用来关闭客户端到服务器的数据传送，然后等待服务器的确认。其中终止标志位FIN=1，序列号seq=u。</p>
<p>step2：第二次挥手<br>服务器收到这个FIN，它发送一个ACK，确认ack为收到的序号加一。</p>
<p>step3：第三次挥手<br>关闭服务器到客户端的连接，发送一个FIN给客户端。</p>
<p>step4：第四次挥手<br>客户端收到FIN后，并发回一个ACK报文确认，并将确认序号seq设置为收到序号加一。首先进行关闭的一方将执行主动关闭，而另一方执行被动关闭。</p>
<p>客户端发送FIN后，进入终止等待状态，服务器收到客户端连接释放报文段后，就立即给客户端发送确认，服务器就进入CLOSE_WAIT状态，此时TCP服务器进程就通知高层应用进程，因而从客户端到服务器的连接就释放了。此时是“半关闭状态”，即客户端不可以发送给服务器，服务器可以发送给客户端。<br>此时，如果服务器没有数据报发送给客户端，其应用程序就通知TCP释放连接，然后发送给客户端连接释放数据报，并等待确认。客户端发送确认后，进入TIME_WAIT状态，但是此时TCP连接还没有释放，然后经过等待计时器设置的2MSL后，才进入到CLOSED状态。</p>
<p>2.为什么需要2MSL时间？<br>首先，MSL即Maximum Segment Lifetime，就是最大报文生存时间，是任何报文在网络上的存在的最长时间，超过这个时间报文将被丢弃。《TCP/IP详解》中是这样描述的：MSL是任何报文段被丢弃前在网络内的最长时间。RFC 793中规定MSL为2分钟，实际应用中常用的是30秒、1分钟、2分钟等。</p>
<p>TCP的TIME_WAIT需要等待2MSL，当TCP的一端发起主动关闭，三次挥手完成后发送第四次挥手的ACK包后就进入这个状态，等待2MSL时间主要目的是：防止最后一个ACK包对方没有收到，那么对方在超时后将重发第三次握手的FIN包，主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用，要等到2MSL时间结束才可以继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。</p>
<p>3.为什么是四次挥手，而不是三次或是五次、六次？<br>双方关闭连接要经过双方都同意。所以，首先是客服端给服务器发送FIN，要求关闭连接，服务器收到后会发送一个ACK进行确认。服务器然后再发送一个FIN，客户端发送ACK确认，并进入TIME_WAIT状态。等待2MSL后自动关闭。</p>
<p>总结：</p>
<p>（1）为了保证客户端发送的最后一个ACK报文段能够到达服务器。即最后一个确认报文可能丢失，服务器会超时重传，然后服务器发送FIN请求关闭连接，客户端发送ACK确认。一个来回是两个报文生命周期。</p>
<p>如果没有等待时间，发送完确认报文段就立即释放连接的话，服务器就无法重传，因此也就收不到确认，就无法按步骤进入CLOSED状态，即必须收到确认才能close。<br>（2）防止已经失效的连接请求报文出现在连接中。经过2MSL，在这个连续持续的时间内，产生的所有报文段就可以都从网络消失。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/">
                微服务SpringCloud之配置中心和消息总线
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-09-10</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p> 在<a href="https://www.cnblogs.com/5ishare/p/11317913.html" target="_blank" rel="noopener">微服务SpringCloud之Spring Cloud Config配置中心SVN</a>博客中每个client刷新配置信息时需要post请求/actuator/refresh,但客户端越来越多时，，需要每个客户端都执行一遍，这种方案就不太适合了。使用Spring Cloud Bus可以完美解决这一问题。</p>
<p>一、Spring Cloud Bus</p>
<p>Spring cloud bus通过轻量消息代理连接各个分布的节点。这会用在广播状态的变化（例如配置变化）或者其他的消息指令。Spring bus的一个核心思想是通过分布式的启动器对spring boot应用进行扩展，也可以用来建立一个多个应用之间的通信频道。目前唯一实现的方式是用AMQP消息代理作为通道，同样特性的设置（有些取决于通道的设置）在更多通道的文档中。</p>
<p>Spring cloud bus被国内很多都翻译为消息总线，也挺形象的。大家可以将它理解为管理和传播所有分布式项目中的消息既可，其实本质是利用了MQ的广播机制在分布式的系统中传播消息，目前常用的有Kafka和RabbitMQ。利用bus的机制可以做很多的事情，其中配置中心客户端刷新就是典型的应用场景之一，我们用一张图来描述bus在配置中心使用的机制。</p>
 <img src="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/w1.png">

<p>二、启动RabbitMq</p>
<p>启动RabbitMq的具体方法之前博客已经写了，略过。</p>
<p>三、SpringCloud Config Server端</p>
<p>1.引入依赖</p>
<p>Demo是在上篇博客的基础上进行修改，主要增加引入spring-cloud-starter-bus-amqp。</p>
<p> View Code</p>
<p>2.新增RabbitMq配置信息</p>
<p>这里主要增加开启消息跟踪、配置rabbitmq相关信息。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">spring.cloud.bus.trace.enabled=true</span><br><span class="line">spring.rabbitmq.host=127.0.0.1</span><br><span class="line">spring.rabbitmq.port=5672</span><br><span class="line">spring.rabbitmq.username=guest</span><br><span class="line">spring.rabbitmq.password=guest</span><br><span class="line">management.endpoints.web.exposure.include=*</span><br></pre></td></tr></table></figure>

<p>四、SpringCloud Config Client端</p>
<p>1.引入依赖</p>
<p>Client端和服务端有类似的配置，也是引入spring-cloud-starter-bus-amqp，增加rabbitmq相关配置。</p>
<p>View Code</p>
<p>2.新增RabbitMq配置信息</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">management.endpoints.web.exposure.include=*</span><br><span class="line">## 开启消息跟踪</span><br><span class="line">spring.cloud.bus.trace.enabled=true</span><br><span class="line">spring.rabbitmq.host=127.0.0.1</span><br><span class="line">spring.rabbitmq.port=5672</span><br><span class="line">spring.rabbitmq.username=guest</span><br><span class="line">spring.rabbitmq.password=guest</span><br></pre></td></tr></table></figure>

<p>五、测试</p>
<p>1.依次启动EurekaServer、SpringCloudConfigServer、SpringCloudConfigClient，输入<a href="http://localhost:8001/neo-config/dev" target="_blank" rel="noopener">http://localhost:8001/neo-config/dev</a>、<a href="http://localhost:8003/hello" target="_blank" rel="noopener">http://localhost:8003/hello</a>。</p>
 <img src="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/w2.png">

 <img src="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/w3.png">

<p>2.修改配置信息</p>
<p>修改github上的配置信息，再次输入上面的url，在8003端口的是没有更新的，此时需要post请求<a href="http://localhost:8001/actuator/bus-refresh来刷新SpringCloudConfigServer。这里在post请求时可能会出现405、404的错误，需要设置management.endpoints.web.exposure.include=*，并且由于springcloud的版本不同，post请求的url也不同。" target="_blank" rel="noopener">http://localhost:8001/actuator/bus-refresh来刷新SpringCloudConfigServer。这里在post请求时可能会出现405、404的错误，需要设置management.endpoints.web.exposure.include=*，并且由于springcloud的版本不同，post请求的url也不同。</a></p>
 <img src="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/w4.png">

<p> post请求之后返回204，然后刷新即可看到最新的配置信息。</p>
 <img src="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/w5.png">

 <img src="/blog/2019/09/10/微服务SpringCloud之配置中心和消息总线/w6.png">




        </div>
    

</div>
            
        </section>
    </div>
</div>



    <div class="row">
        <div class="col-sm-12">
            <div class="wrap-pagination">
                <a class="disabled" href="/blog/">
                    <i class="fa fa-chevron-left" aria-hidden="true"></i>
                </a>
                <a class="" href="/blog/page/2/">
                    <i class="fa fa-chevron-right" aria-hidden="true"></i>
                </a>
            </div>
        </div>
    </div>




</div>

<!-- Footer -->
<div class="push"></div>

<footer class="footer-content">
    <div class="container">
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-6 col-lg-6 footer-about">
                <h2>About</h2>
                <p>
                    This theme was developed by <a href="https://github.com/klugjo">Jonathan Klughertz</a>. The source code is available on Github. Create Websites. Make Magic.
                </p>
            </div>
            
    <div class="col-xs-6 col-sm-6 col-md-3 col-lg-3 recent-posts">
        <h2>Recent Posts</h2>
        <ul>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/25/tars框架环境基础搭建/">tars框架环境基础搭建</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/20/认识tars框架/">认识tars框架</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/05/redis数据迁移备份与恢复/">redis数据迁移备份与恢复</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/09/21/负载均衡的5种策略/">负载均衡的5种策略</a>
            </li>
            
        </ul>
    </div>



            
        </div>
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <ul class="list-inline footer-social-icons">
                    
                    <li class="list-inline-item">
                        <a href="https://github.com/klugjo/hexo-theme-alpha-dust">
                            <span class="footer-icon-container">
                                <i class="fa fa-github"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://twitter.com/?lang=en">
                            <span class="footer-icon-container">
                                <i class="fa fa-twitter"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.facebook.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-facebook"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.instagram.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-instagram"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://dribbble.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-dribbble"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://plus.google.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-google-plus"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.behance.net/">
                            <span class="footer-icon-container">
                                <i class="fa fa-behance"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://500px.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-500px"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="mailto:test@example.com">
                            <span class="footer-icon-container">
                                <i class="fa fa-envelope-o"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="\#">
                            <span class="footer-icon-container">
                                <i class="fa fa-rss"></i>
                            </span>
                        </a>
                    </li>
                    
                </ul>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <div class="footer-copyright">
                    @Untitled. All right reserved | Design & Hexo <a href="http://www.codeblocq.com/">Jonathan Klughertz</a>
                </div>
            </div>
        </div>
    </div>
</footer>

<!-- After footer scripts -->

<!-- jQuery -->
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>

<!-- Tween Max -->
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenMax.min.js"></script>

<!-- Gallery -->
<script src="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.js" type="text/javascript" charset="utf-8"></script>

<!-- Custom JavaScript -->
<script src="/blog/js/main.js"></script>

<!-- Disqus Comments -->



</body>

</html>